package com.nulldev.util.graphics.renderIt.util.osdep;

import java.awt.Graphics;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.JVM.reflections.Reflections;
import com.nulldev.util.VariableAPI.StringsUtil;
import com.nulldev.util.VariableAPI.util.strings.splitters.Splitters;
import com.nulldev.util.data.Variables;
import com.nulldev.util.graphics.renderIt.api.envcaps.renderItOperations;
import com.nulldev.util.osAPI.OS;
import com.nulldev.util.processAPI.Processes;

public class OSDependentExtensions {

	public static final renderItOperations[] get_os_operations(final Graphics g) {
		if (OS.isWindows() && Reflections.is("sun.java2d.SunGraphics2D") && Reflections.use("sun.java2d.SunGraphics2D").methods().contains("markDirty"))
			return new renderItOperations[]
				{ renderItOperations.WINDOWS_invalidate_surface };
		if (OS.isLinux())
			return new renderItOperations[]
				{ renderItOperations.LINUX_environment_info };
		if (OS.isAndroid())
			return new renderItOperations[]
				{ renderItOperations.ANDROID_battery_info, renderItOperations.ANDROID_environment_info, renderItOperations.ANDROID_renderer_info };
		return new renderItOperations[0];
	}

	public static class OSDEPAndroidBatteryInfo {
		public final boolean isBatterySaving, isCharging, isLowPower;
		public final float batteryPercentage;

		protected OSDEPAndroidBatteryInfo(final boolean batterySaving, final boolean charging, final boolean lowPower, final float percentage) {
			this.isBatterySaving = batterySaving;
			this.isCharging = charging;
			this.isLowPower = lowPower;
			this.batteryPercentage = percentage;
		}

		protected static final OSDEPAndroidBatteryInfo FALLBACK = new OSDEPAndroidBatteryInfo(false, true, false, 100.0f);
	}

	public static final OSDEPAndroidBatteryInfo android_get_battery_info() {
		return android_get_battery_info(null);
	}

	public static final OSDEPAndroidBatteryInfo android_get_battery_info(final Object context) {
		if (!OS.isAndroid())
			throw new UnsupportedOperationException("Invalid OS for ANDROID_battery_info.");
		if (Reflections.is("com.nulldev.util.android.virtual.os")) { // TODO: Move to the new Reflections API
			final Reflections batteryManager = Reflections
					.encapsulate_experimental(Reflections.use("com.nulldev.util.android.virtual.os.BatteryManager").invoke("get", context));
			final int percentage = (int) batteryManager.invoke("getIntProperty", /* BATTERY_PROPERTY_CAPACITY */ 4);
			final boolean charging = (boolean) batteryManager.invoke("isCharging");
			return new OSDEPAndroidBatteryInfo(false, charging, (percentage <= 20 && !charging), percentage);
		} else {
			return OSDEPAndroidBatteryInfo.FALLBACK;
		}
	}

	public static final String os_linux_get_version() {
		if (!OS.isLinux())
			throw new UnsupportedOperationException("Invalid OS for LINUX_environment_info.");
		try {
			final String out = Processes.execCmd_NoQueue("cat /proc/version");
			final String[] sp = Splitters.splitString(out, " ");
			return sp[2];
		} catch (Throwable ex) {
			return null;
		}
	}

	public static final String os_linux_get_distro() {
		if (!OS.isLinux())
			throw new UnsupportedOperationException("Invalid OS for LINUX_environment_info.");
		try {
			final String out = Processes.execCmd_NoQueue("cat /etc/os-release");
			return StringsUtil.substringBetweenF(out, "PRETTY_NAME=\"", "\"", "Generic Linux");
		} catch (Throwable ex) {
			return null;
		}
	}

	public static final void invalidateSurface(final Graphics g) {
		if (!OS.isWindows())
			throw new UnsupportedOperationException("Invalid OS for WINDOWS_invalidate_surface.");
		if (!Reflections.use("sun.java2d.SunGraphics2D").methods().contains("markDirty"))
			throw new UnsupportedOperationException("Cannot use WINDOWS_invalidate_surface: markDirty(void) is missing.");
		Variables.requireNonNull(g, "g");
		Reflections.encapsulate(g).invoke("markDirty");
	}

	public static void main(String[] args) {
		if (OS.isLinux()) {
			JVM.println("os_linux_get_version: " + os_linux_get_version());
			JVM.println("os_linux_get_distro: " + os_linux_get_distro());
		}
		if (OS.isAndroid()) {
			final OSDEPAndroidBatteryInfo abinf = android_get_battery_info();
			JVM.println("batterySaving: " + abinf.isBatterySaving);
			JVM.println("isLowPower: " + abinf.isLowPower);
			JVM.println("isCharging: " + abinf.isCharging);
			JVM.println("batteryPercentage: " + abinf.batteryPercentage);
		}
	}
}
